import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import { isEmpty } from 'lodash'
import { getDefaultWhiteList, FilterXSS } from 'xss'
import { userModule } from '@/common/store/modules/user'
dayjs.extend(utc) // 配置 UTC 插件
export const conversionUtcDate = (date: string, type: string) => {
  if (type === 'local') {
    // 将UTC时间转换为本地时间
    return dayjs.utc(date).local().format('YYYY-MM-DD HH:mm:ss')
  } else if (type === 'UTC') {
    // 将时间转换为UTC时间
    return dayjs(date).utc().format()
  }
}

export const newDate = () => {
  const now = new Date()
  const diff = now.getTimezoneOffset() // 格林威治时间和本地时间的时差
  const stamp = new Date().getTime() + diff * 60 * 1000 + 8 * 60 * 60 * 1000 // 东八区时间戳
  const date = new Date(stamp - userModule().timedifference)
  return date
}

export const deepClone = (targetObj: any) => {
  // 深拷贝
  let tempObj: any
  if (typeof targetObj === 'object') {
    if (targetObj === null) {
      tempObj = null
    } else {
      if (targetObj instanceof Date) {
        tempObj = targetObj
      } else if (targetObj instanceof Array) {
        tempObj = []
        for (let i = 0, len = targetObj.length; i < len; i++) {
          tempObj.push(deepClone(targetObj[i]))
        }
      } else {
        tempObj = {}
        for (const j in targetObj) {
          tempObj[j] = deepClone(targetObj[j])
        }
      }
    }
  } else {
    tempObj = targetObj
  }
  return tempObj
}

// xss过滤
export const filterXSS = (() => {
  const whiteList: any = getDefaultWhiteList() // 获取默认白名单
  // 添加新的白名单标签或属性
  for (const i of Object.keys(whiteList)) {
    whiteList[i].push('style', 'class')
    if (i === 'table' && whiteList[i]) {
      whiteList[i].push('cellpadding', 'cellspacing', 'bordercolor')
    }
  }
  whiteList.strike = ['style', 'class']
  const options = {
    whiteList,
    css: false,
    stripIgnoreTag: true, // 非白名单标签，过滤标签，显示标签里的内容
    stripIgnoreTagBody: ['script', 'style']
  }
  const myxss = new FilterXSS(options)
  return myxss.process.bind(myxss)
})()

/**
 * 获取链接的query参数对象
 * @param url 链接
 * @returns
 */
export const getQuery = (url: string = location.href) => {
  const str = url.match(/\?(.*)/)?.[1]
  return Object.fromEntries(str?.split('&').map((i) => i.split('=')) || [])
}
// 获取当前时间
export function getCurrentDateTime() {
  const date = newDate()
  const year = date.getFullYear()
  let month: any = date.getMonth()
  let day: any = date.getDate()
  let h: any = date.getHours()
  let m: any = date.getMinutes()
  let s: any = date.getSeconds()
  month = month + 1 > 9 ? month + 1 : '0' + (month + 1)
  day = day > 9 ? day : '0' + day
  h = h > 9 ? h : '0' + h
  m = m > 9 ? m : '0' + m
  s = s > 9 ? s : '0' + s
  return year + '-' + month + '-' + day + ' ' + h + ':' + m + ':' + s
}

/**
 * (type: noYear) -->  23:23:34
 * (type: '') -->  2020-10-23 23:23:34
 */
export function getFormatDateTime(date: any, type: string) {
  if (typeof date === 'string') {
    date = new Date(date)
  }
  const year = date.getFullYear()
  let month = date.getMonth()
  let day = date.getDate()
  let hour = date.getHours()
  let minites = date.getMinutes()
  let second = date.getSeconds()
  month = month + 1 > 9 ? month + 1 : '0' + (month + 1)
  day = day > 9 ? day : '0' + day
  hour = hour > 9 ? hour : '0' + hour
  minites = minites > 9 ? minites : '0' + minites
  second = second > 9 ? second : '0' + second
  if (type === 'noYear') {
    return hour + ':' + minites + ':' + second
  } else if (type === 'noTime') {
    return year + '-' + month + '-' + day
  } else {
    return year + '-' + month + '-' + day + ' ' + hour + ':' + minites + ':' + second
  }
}
/**
 * (86401, true) -->  1天0小时0分1秒
 * (86401, false) -->  24:00:01
 */
export const getCallTimeLength = (second: any, format: any) => {
  if (second) {
    let h: any
    let m: any
    let s: any
    if (second === null || second < 0) {
      return
    }
    const d = Math.floor(second / (24 * 3600 * 1000))
    h = (second / 3600) | 0
    second = parseFloat(second) - h * 3600
    if (parseInt(h, 16) < 10) {
      h = '0' + h
    }
    m = (second / 60) | 0
    s = (parseFloat(second) - m * 60).toFixed(0)
    if (parseInt(m, 16) < 10) {
      m = '0' + m
    }
    if (s < 10) {
      s = '0' + s
    }
    if (format) {
      let time = ''
      if (d > 0) {
        time += d + '天'
      }
      if (h > 0) {
        time += h + '时'
      }
      if (m > 0) {
        time += m + '分'
      }
      if (s > 0) {
        time += s + '秒'
      }
      return time
    } else {
      return h + ':' + m + ':' + s
    }
  } else {
    return '00:00:00'
  }
}

// 手机号
export const encryptPhone = (phone: string) => {
  if (!phone) {
    return ''
  }
  const len = phone.length
  if (len < 6) {
    return phone
  }
  let tel = ''
  const mobile = /1[3,4,5,7,8][0-9]{9}/
  if (mobile.test(phone)) {
    tel = phone.substring(0, 3) + '****' + phone.substring(7)
  } else {
    const p = len / 2
    tel = phone.substring(0, p - 2) + '****' + phone.substring(p + 2)
  }
  return tel
}

/**
 * 带有层级名pathName（a/b/c）的扁平化函数
 * @param tree
 * @param childrenKey
 * @returns
 */
export const flatten: any = (tree: any, childrenKey = 'children') => {
  tree.forEach((i: any) => {
    if (!flatten.res) {
      flatten.res = []
    }
    flatten.res.every((m: any) => m._id !== i._id) && flatten.res.push(i)
    if (!isEmpty(i[childrenKey])) {
      flatten(i[childrenKey], childrenKey)
    }
  })
  flatten.res.forEach((i: any) => {
    if (isEmpty(i.children)) {
      i.pathName = i.name
    }
  })
  flatten.res.forEach((i: any, m: number) => {
    const next = flatten.res[m + 1]
    if (next && next.parentId && next.parentId === i._id) {
      next.pathName = `${i.pathName ?? i.name}/${next.name}`
    }
  })
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  return flatten.res.filter((i: any) => i.pathName && !i.children?.length)
}

/**
 * 扁平化函数
 * @param tree
 * @param childrenKey
 * @returns
 */
export const normalFlatten: any = (tree: any, childrenKey = 'children') => {
  tree.forEach((i: any) => {
    if (!flatten.res) {
      flatten.res = []
    }
    flatten.res.every((m: any) => m._id !== i._id) && flatten.res.push(i)
    if (!isEmpty(i[childrenKey])) {
      flatten(i[childrenKey], childrenKey)
    }
  })
  return flatten.res
}

export const Base64 = {
  _keyStr: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
  encode: (input: any) => {
    let output = ''
    let i = 0
    input = Base64._utf8_encode(input)
    while (i < input.length) {
      const chr1 = input.charCodeAt(i++)
      const chr2 = input.charCodeAt(i++)
      const chr3 = input.charCodeAt(i++)
      const enc1 = chr1 >> 2
      const enc2 = ((chr1 & 3) << 4) | (chr2 >> 4)
      let enc3 = ((chr2 & 15) << 2) | (chr3 >> 6)
      let enc4 = chr3 & 63
      if (isNaN(chr2)) {
        enc3 = 64
        enc4 = 64
      } else if (isNaN(chr3)) {
        enc4 = 64
      }
      output =
        output +
        Base64._keyStr.charAt(enc1) +
        Base64._keyStr.charAt(enc2) +
        Base64._keyStr.charAt(enc3) +
        Base64._keyStr.charAt(enc4)
    }
    return output
  },
  decode: (input: any) => {
    let output = ''
    let i = 0
    // todo []中括号里面使用转移符是多余的
    // input = input.replace(/[^A-Za-z0-9\+\/\=]/g, '')
    input = input.replace(/[^A-Za-z0-9\u002b\u002f\u003d]/g, '')
    while (i < input.length) {
      const enc1 = Base64._keyStr.indexOf(input.charAt(i++))
      const enc2 = Base64._keyStr.indexOf(input.charAt(i++))
      const enc3 = Base64._keyStr.indexOf(input.charAt(i++))
      const enc4 = Base64._keyStr.indexOf(input.charAt(i++))
      const chr1 = (enc1 << 2) | (enc2 >> 4)
      const chr2 = ((enc2 & 15) << 4) | (enc3 >> 2)
      const chr3 = ((enc3 & 3) << 6) | enc4
      output = output + String.fromCharCode(chr1)
      if (enc3 !== 64) {
        output = output + String.fromCharCode(chr2)
      }
      if (enc4 !== 64) {
        output = output + String.fromCharCode(chr3)
      }
    }
    output = Base64._utf8_decode(output)
    return output
  },
  _utf8_encode: (string1: string) => {
    const str = string1.replace(/\r\n/g, '\n')
    let utftext = ''
    for (let n = 0; n < str.length; n++) {
      const c = str.charCodeAt(n)
      if (c < 128) {
        utftext += String.fromCharCode(c)
      } else if (c > 127 && c < 2048) {
        utftext += String.fromCharCode((c >> 6) | 192)
        utftext += String.fromCharCode((c & 63) | 128)
      } else {
        utftext += String.fromCharCode((c >> 12) | 224)
        utftext += String.fromCharCode(((c >> 6) & 63) | 128)
        utftext += String.fromCharCode((c & 63) | 128)
      }
    }
    return utftext
  },
  _utf8_decode: (utftext: string) => {
    let str = ''
    let i = 0
    let [c, c2, c3] = [0, 0, 0]
    while (i < utftext.length) {
      c = utftext.charCodeAt(i)
      if (c < 128) {
        str += String.fromCharCode(c)
        i++
      } else if (c > 191 && c < 224) {
        c2 = utftext.charCodeAt(i + 1)
        str += String.fromCharCode(((c & 31) << 6) | (c2 & 63))
        i += 2
      } else {
        c2 = utftext.charCodeAt(i + 1)
        c3 = utftext.charCodeAt(i + 2)
        str += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63))
        i += 3
      }
    }
    return str
  }
}

// 地区扁平化
export const hanleAreaMap = (cur: any) => {
  const labels: any = {}
  const handleFn = (list: any) => {
    list.map((item: any) => {
      labels[item.id] = item.fullname
      if (item.children) {
        handleFn(item.children)
      }
    })
  }
  if (cur && Array.isArray(cur)) {
    handleFn(cur)
  }
  return labels || {}
}

// 表单校验有问题时，滚动到第一个el-error的位置
export function formRollToFirstError(paneNode: any, revise = 0) {
  setTimeout(() => {
    // 延时是为了解决偶发异步取不到is-error节点
    const pane = paneNode.getElementsByClassName('is-error')[0]
    if (pane) {
      paneNode.scrollTop = pane.offsetTop + revise
      const textareaNode = pane.getElementsByClassName('el-textarea__inner') // 多行文本
      const inputNode = pane.getElementsByClassName('el-input__inner') // 单行文本，日期，日期时间，下拉框，数字等
      if (textareaNode && textareaNode[0]) {
        textareaNode[0].focus()
      } else if (inputNode && inputNode[0]) {
        inputNode[0].focus()
      }
    }
  }, 100)
}
